home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 05 - 1989 / 05.07 Jul 89 / JamPaint ƒ / JamPaint.p < prev    next >
Encoding:
Text File  |  1988-06-19  |  60.9 KB  |  2,708 lines  |  [TEXT/MPS ]

  1. Program JamPaint;
  2. {
  3.     *************************************************
  4.     
  5.         JamPaint -- the Network Paint Application
  6.     
  7.     *************************************************
  8.     
  9.     Copyright 1988 by Edgar Circenis and Rod Magnuson
  10.     All Rights Reserved
  11.     
  12.     *************************************************
  13.     
  14.         Started: 12/26/87        Revision: 5/21/88
  15.     
  16.     *************************************************
  17.  
  18.     Problem areas:
  19.         - Do we need to worry about nets as well as nodes?
  20.         - How big should PQ be?
  21.         - VBLTasks cannot move memory.
  22.         - Change xEnqueue and xDequeue to access PQ directly.
  23.         - What causes initial LAPWrite error @70 (err = -95)???
  24.         - NOTE: if we end up using polling, a queue will be unnecessary.
  25.         - use VAR parameters where it will speed things up.
  26.     
  27.     *************************************************
  28. }
  29.     USES
  30.         {$LOAD MacDump}
  31.         Memtypes,Quickdraw,OSIntf,ToolIntf,PackIntf,PickerIntf,Script,
  32.         {$LOAD AppleTalkDump}
  33.         AppleTalk,
  34.         {$LOAD MacPrintDump}
  35.         PrintTraps;
  36.     
  37.     CONST
  38.         lastMenu        = 7;
  39.         maxUsers        = 8;            { User Table size }
  40.         OurType        = 39;            { a random LAP protocol type }
  41.         listSize        = 550;        { incoming packet queue size }        
  42.         VBLcnt        = 2;            { myTask.vblCount }
  43.         connect        = false;
  44.         spray            = true;
  45.         idleTime        = 60*60*5;    { five minute idle time }
  46.         eraseCursor = 128;
  47.         splatCursor = 8088;        { splatter cursor ID }
  48.         
  49.         { ---- TOOLS ---- }
  50.         Tnone = 0;                    { no tool, or special tool }
  51.         Tspray    =    1;                { not really a tool! }
  52.         TLetters    =    2;                { letter tool }
  53.         Tbrush    =    3;                { paint brush }
  54.         Terase    =    4;                { eraser }
  55.         TRect        =    5;                { Rectangle }
  56.         TFrect    =    6;                { Filled Rectangle }
  57.         TOval        =    7;                { Oval }
  58.         TFOval    =    8;                { Filled Oval }
  59.         TSplatter=    9;                { Splatter Tool }
  60.         TDisk        = 10;                { Disk Access }
  61.         Tpat        = 11;                { not a tool }
  62.         Tcolor    = 12;                { not a tool }
  63.         
  64.         { ---- DEFAULTS ---- }
  65.         dSize        =    12;
  66.         dStyle    =    [];
  67.         dPen        =    1;    { 1 x 1 pen }
  68.         dColor    =    1;    { black }
  69.         dTool        =    Tbrush;
  70.         dMode        =    connect;
  71.         
  72.         dsplatterCount = 30;    { * default spatter speed * }
  73.         dsplatRad        = 20;    { * default splatter radius * }
  74.         
  75.         { **** make a decision about this and then delete it **** }
  76.         polling = true;
  77.         { **** make a decision about this and then delete it **** }
  78.         
  79.         appleMenu    =    1;
  80.         fileMenu        =    2;
  81.         fontMenu        =    3;
  82.         sizeMenu        =    4;
  83.         styleMenu    =    5;
  84.         effectsMenu    =    6;
  85.         editMenu        =    7;
  86.         
  87.     TYPE
  88.         UserTableRec =    record
  89.                                 id                :integer;        { appleTalk id }
  90.                                 time            :longint;        { idle time }
  91.                                 theTool        :integer;        { current tool }
  92.                                 x,y            :integer;        { mouse coordinates }
  93.                                 theMode        :boolean;        { paint mode }
  94.                                 thePat        :pattern;        { current pattern }
  95.                                 theClr        :RGBColor;        { current color }
  96.                                 hSize,vSize    :integer;        { penSize }
  97.                                 theFnum        :integer;        { font number }
  98.                                 theFsize        :integer;        { font size }
  99.                                 theFstyle    :style;            { font style }
  100.                                 splatRad        :integer;        { splatter tool's radius }
  101.                                 splatSpeed    :integer;        { splatter tool's speed }
  102.                             end;
  103.         
  104.         MSGType = (paintMode,alpha,settool,eraseall,setpat,setcolor,setpen,setfont,setpos,drag,rectpck,setSplat,rqinfo,sendinfo);
  105.         LAPMsg = record
  106.                         size        :packed array [0..1] of byte;    { packet length }
  107.                         theType    :MSGType;                            { message type }
  108.                         id            :byte;                                { node id }
  109.                         case MSGType of
  110.                             paintMode:    (mode    :boolean);        { select paint mode type: connect, spray }
  111.                             alpha:        (ch    :char);            { type char in current font, size, style, location }
  112.                             settool:        (tool    :integer);        { select a tool }
  113.                             setpat:        (pat    :pattern);        { select a pattern }
  114.                             setcolor:    (clr    :RGBColor);        { select a color }
  115.                             setpen:        (px,py:integer);        { set pen size to px,py }
  116.                             setfont:        (fnum    :integer;        { select font characteristics }
  117.                                              fsize:integer;
  118.                                              fstyl:style);
  119.                             setpos:        (mx,my:integer);        { set current position to mx,my }
  120.                             drag:            (cx,cy:integer);        { mouse dragged from mx,my to cx,cy }
  121.                             setSplat:    (sRad:integer;            { resize splatter tool }
  122.                                              sSpeed:integer);
  123.                             rectpck:        (rct    :rect;            { rectangle for TRect..TFOval }
  124.                                              optDown:boolean);
  125.                             sendinfo:    (info    :UserTableRec);{ user info }
  126.                     end;
  127.         LAPMsgPtr = ^LAPMsg;
  128.         PacketList = Packed array [0..listSize-1] of LAPMsg;
  129.         PacketQueue =    record
  130.                                 head        :integer;
  131.                                 tail        :integer;
  132.                                 queue        :PacketList;
  133.                             end;
  134.         PacketQueuePtr = ^PacketQueue;
  135.         
  136.         CArry        =    Array [1..8] of RGBColor;
  137.         CPtr        =    ^CArry;
  138.         CHandle    =    ^CPtr;
  139.         
  140.         BitMapPtr    =    ^BitMap;
  141.     VAR
  142.         {
  143.             A NOTE ABOUT GLOBALS AND SUCH:
  144.             Everyone and their brother is taught that using global variables
  145.             is a sin.  We do not agree.  By using many globals and declaring
  146.             parameters in parameter lists to be VAR parameters (even when
  147.             not needed), we increase the speed of our code by reducing stack
  148.             frame size and the creation of local copies of variables.
  149.         }
  150.         myEvent                            :EventRecord;
  151.         theItem,theMenu,refnum        :integer;
  152.         theChar                            :Char;
  153.         code                                :integer;
  154.         tempWindow,myWindow             :WindowPtr;
  155.         doneflag                         :boolean;
  156.         PrDebug                            :boolean;
  157.         mods                                :longint;
  158.  
  159.         mymenus                            :array [1..lastmenu] of MenuHandle;
  160.         FileMenuPresent                :boolean;
  161.         err                                :integer;
  162.         dlg                                :DialogPtr;
  163.         itype                             :integer;
  164.         item                                :handle;
  165.         box                                :rect;
  166.         itemHit                            :integer;
  167.         
  168.         myTask                            :VBLTask;
  169.         
  170.         UT                                    :array [0..maxUsers] of UserTableRec;
  171.         PQ                                    :PacketQueue;
  172.         myNode,myNet                    :integer;
  173.         LAPrh,LAPwh                        :ABRecHandle;
  174.         LAPrbuf,LAPwbuf                :LAPMsg;
  175.         
  176.         DrawWindow                        :WindowPtr;
  177.         drect,prect                        :rect;
  178.         jamPic,palette                    :picHandle;
  179.         ToolRects                        :array[1..20] of Rect;
  180.         curPatRect                        :rect;
  181.         hSizeRect,vSizeRect            :rect;
  182.         PatternsUp                        :Boolean;
  183.         thePatterns                        :array [1..8] of pattern;
  184.         theColors                        :CArry;
  185.         curPat,curColor                :integer;
  186.         
  187.         theFontidx                        :integer;
  188.         theSizeidx                        :integer;
  189.         
  190.         clickTime                        :longint;
  191.         lastTool                            :integer;
  192.         theECurs,theCurs                :cursor;
  193.         arrowCurs,updateCurs            :boolean;
  194.         bmap,Wbits                        :bitmap;
  195.         oldRgn,oldClip                    :RgnHandle;
  196.         
  197.         changed,saved                    :boolean;
  198.         fVref                                :integer;
  199.         
  200.         MultiFinderRunning            :boolean;
  201.         ColorQDrawImplm                :boolean;
  202.         MacII,PixDraw                    :boolean;
  203.         myCGrafPtr                        :CGrafPtr;
  204.         myCGrafPort                        :CGrafPort;
  205.         ourCMHandle                        :CTabHandle;
  206.         offpix,Wpix                        :PixMapHandle;
  207.         
  208.         theHand,theSizer                :CursHandle;
  209.         theSprayer,thePlacer            :CursHandle;
  210.         
  211.         hPrint                            :THPrint;
  212.         
  213.     Procedure SendLAP(who:byte);    Forward;
  214.     Procedure CheckRead;                Forward;
  215.     Procedure DrawContents;            Forward;
  216.     
  217.     
  218.     Procedure Debug(s:str255);
  219.         begin
  220.             if PrDebug then
  221.                 begin
  222.                     PrCtlCall(iPrIOCtl,ord(@s)+1,length(s),0);
  223.                     PrCtlCall(iPrDevCtl,$0003FFFF,0,0);
  224.                 end;
  225.         end;
  226.     
  227.     
  228.     Function Str(i:longInt):str255;        { These two functions are invaluable }
  229.         begin
  230.             NumToString(i,Str);
  231.         end;
  232.     
  233.     
  234.     Function Val(s:str255):longint;
  235.         begin
  236.             StringToNum(s,Val);
  237.         end;
  238.     
  239.     
  240.     function MyGetNextEvent(evtMask:Integer;VAR Evt:EventRecord):Boolean;
  241.         { * This allows us to be more MultiFinder compatible * }
  242.         begin
  243.             If MultiFinderRunning then
  244.                 MyGetNextEvent:=WaitNextEvent(evtMask,Evt,15,Nil)
  245.             else
  246.                 begin
  247.                     SystemTask;
  248.                     MyGetNextEvent:=GetNextEvent(evtMask,Evt);
  249.                 end;
  250.         end;
  251.  
  252.  
  253.     Procedure MenuString(s:str255);        { good for debugging simple stuff }
  254.         var
  255.             dMenu    :MenuHandle;
  256.         begin
  257.             s := Concat(s,' <click>');
  258.             DMenu := NewMenu(999,s);
  259.             InsertMenu(DMenu,0);
  260.             DrawMenuBar;
  261.             sysBeep(1);
  262.             repeat Until MyGetNextEvent(mdownMask+keyDownMask+AutoKeyMask,myEvent);
  263.             DeleteMenu(999);
  264.             DisposeMenu(DMenu);
  265.             DrawMenuBar;
  266.         end;
  267.  
  268.  
  269.     Function idleFilter(item:Integer;theDlg:DialogPtr):Integer;
  270.         begin
  271.             SetUpA5;
  272.             idleFilter:=item;
  273.             CheckRead;
  274.             RestoreA5;
  275.         end;
  276.  
  277.  
  278.     procedure HiliteButton(theDialog:DialogPtr);
  279.         begin
  280.             SetPort(theDialog);
  281.             GetDItem(theDialog,ok,iType,iTem,Box);
  282.             InsetRect(Box,-4,-4);
  283.             PenSize(3,3);
  284.             FrameRoundRect(box,15,16);
  285.             PenNormal;
  286.         end;
  287.  
  288.  
  289.     Procedure DoErr(i:integer);
  290.         begin
  291.             if err<>0 then
  292.                 begin
  293.                     if prDebug then
  294.                         Debug(concat('*** ',str(i),':  error = ',str(err)))
  295.                     else
  296.                         menuString(concat(str(i),':  error = ',str(err)));
  297.                 end;
  298.         end;
  299.         
  300.  
  301.     Procedure RsrcErr;
  302.         begin
  303.             if ResError<>0 then
  304.                 begin
  305.                     if PrDebug then
  306.                         Debug(concat('*** RsrcErr=',str(ResError)))
  307.                     else
  308.                         menuString(concat('RsrcErr=',str(ResError)));
  309.                 end;
  310.         end;
  311.         
  312.  
  313.     Procedure SetUpMenus;
  314.         var
  315.             i            :integer;
  316.             s,fName    :str255;
  317.             
  318.         begin
  319.             InitMenus;
  320.             FileMenuPresent:=false;
  321.             
  322.             for i := 1 to lastmenu do
  323.                 MyMenus[i] := GetMenu(254+i);
  324.             for i := 1 to lastmenu-1 do
  325.                 InsertMenu(myMenus[i],0);
  326.             AddResMenu(MyMenus[appleMenu],'DRVR');
  327.             AddResMenu(MyMenus[fontMenu],'FONT');
  328.             GetFontName(applFont,fName);
  329.             for i := 1 to countMItems(mymenus[fontMenu]) do
  330.                 begin
  331.                     GetItem(mymenus[fontMenu],i,s);
  332.                     if s=fName then
  333.                         begin
  334.                             CheckItem(mymenus[fontMenu],i,true);
  335.                             theFontidx := i;
  336.                             leave;
  337.                         end;
  338.                 end;
  339.             for i:=1 to 9 do
  340.                 begin
  341.                     GetItem(myMenus[sizeMenu],i,s);
  342.                     if RealFont(theFontidx,Val(s))
  343.                         then
  344.                             SetItemStyle(myMenus[sizeMenu],i,[Outline])
  345.                         else
  346.                             SetItemStyle(myMenus[sizeMenu],i,[]);
  347.                 end;
  348.             DrawMenuBar;
  349.         end;
  350.     
  351.     
  352.     Procedure xEnqueue(var msg:LAPMsg);    { add queue element }
  353.         begin
  354.             Debug('xEnqueue');
  355.             with PQ do
  356.                 if (tail+1) mod listSize = head then
  357.                     begin
  358.                         sysbeep(1);        { oops, queue full! }
  359.                         Debug('Queue Full');
  360.                     end
  361.                 else
  362.                     begin
  363.                         queue[tail] := msg;
  364.                         tail := (tail+1) mod listSize;
  365.                         Debug(concat(' head=',str(head),', tail=',str(tail)));
  366.                     end;
  367.         end;
  368.     
  369.     
  370.     Function xDequeue(var msg:LAPMsg):boolean;    { remove first queue element }
  371.         begin
  372.             with PQ do
  373.                 if tail=head then
  374.                     xDequeue := false
  375.                 else
  376.                     begin
  377.                         Debug('xDequeue: dequeued');
  378.                         msg := queue[head];
  379.                         head := (head+1) mod listsize;
  380.                         xDequeue := true;
  381.                         Debug(concat(' head=',str(head),', tail=',str(tail)));
  382.                     end;
  383.         end;
  384.     
  385.     procedure DoPageSetUp;
  386.         var
  387.             temphPrint    :    THPrint;
  388.             err            :    OSErr;
  389.             
  390.         begin
  391.             PrOpen;
  392.             If PrError=noErr then
  393.                 begin
  394.                     temphPrint:=hPrint;
  395.                     err:=HandToHand(handle(temphPrint));
  396.                     Repeat
  397.                         if PrStlDialog(temphPrint) then
  398.                             begin
  399.                                 DisposHandle(handle(hPrint));
  400.                                 If MemError<>NoErr then
  401.                                     SysBeep(1);
  402.                                     
  403.                                 hPrint:=temphPrint;
  404.                                 err:=HandToHand(handle(hPrint));
  405.                                 if err<>NoErr then
  406.                                     SysBeep(1);
  407.                             end;
  408.                     Until not PrValidate(hPrint);
  409.                 end;
  410.             PrClose;
  411.             DisposHandle(handle(temphPrint));
  412.         end;
  413.  
  414.     Function FindUser(id:integer):integer;        { find a user's UT entry }
  415.     {
  416.         find user in UT.  If not in UT, return -1 and
  417.         send <rqinfo> packet to user if table not yet full.
  418.         If data is not valid, returns -(index+1).
  419.     }
  420.         var
  421.             i        :integer;
  422.             
  423.         begin
  424.             Debug('FindUser');
  425.             for i := 0 to maxUsers do                    { CASE 1: look for user }
  426.                 if UT[i].id=id then
  427.                     begin
  428.                         FindUser := i;                        { valid user found }
  429.                         Debug(' user found');
  430.                         exit(FindUser);
  431.                     end;
  432.             Debug(' user not found');
  433.             for i := 1 to maxUsers do                    { CASE 2: look for empty slot }
  434.                 if UT[i].id<0 then
  435.                     begin
  436.                         UT[i].id := id;
  437.                         LAPwbuf.theType := rqinfo;
  438.                         SendLAP(id);
  439.                         FindUser := -1;                    { user not valid (yet) }
  440.                         exit(FindUser);
  441.                     end;
  442.             for i := 1 to maxUsers do                    { CASE 3: look for idle user }
  443.                 if tickCount-UT[i].time>idleTime then
  444.                     begin
  445.                         UT[i].id := id;
  446.                         LAPwbuf.theType := rqinfo;
  447.                         SendLAP(id);
  448.                         FindUser := -1;                    { user not valid (yet) }
  449.                         exit(FindUser);
  450.                     end;
  451.         end;
  452.     
  453.     
  454.     Procedure SetUserState(j:integer);        { set previous user state }
  455.         begin
  456.             Debug('SetUserState');
  457.             with UT[j] do
  458.                 begin
  459.                     MoveTo(x,y);
  460.                     PenPat(thePat);
  461.                     if MacII then
  462.                         RGBForeColor(theClr);
  463.                     PenSize(hSize,vSize);
  464.                     TextFont(theFnum);
  465.                     TextSize(theFsize);
  466.                     TextFace(theFstyle);
  467.                 end;
  468.         end;
  469.     
  470.     
  471.     Procedure OffBits;        { set offscreen bitmap }
  472.         begin
  473.             if MacII then
  474.                 begin
  475.                     if PixDraw then
  476.                         begin
  477.                             SetPort(GrafPtr(myCGrafPtr));
  478.                         end;
  479.                 end
  480.             else
  481.                 begin
  482.                     oldRgn:=NewRgn;
  483.                     CopyRgn(DrawWindow^.visRgn,oldRgn);
  484.                     RectRgn(DrawWindow^.visRgn,bmap.bounds);
  485.                     
  486.                     Wbits:=DrawWindow^.portbits;
  487.                     SetPortBits(bmap);
  488.                 end;
  489.         end;
  490.     
  491.     
  492.     Procedure OnBits;            { set onscreen bitmap }
  493.         begin
  494.             if MacII
  495.                 then
  496.                     begin
  497.                         if PixDraw then
  498.                             begin
  499.                                 SetPort(DrawWindow);
  500.                             end;
  501.                     end
  502.                 else
  503.                     begin
  504.                         CopyRgn(oldRgn,DrawWindow^.visRgn);
  505.                         DisposeRgn(oldRgn);
  506.                         SetPort(DrawWindow);
  507.                         SetPortBits(Wbits);
  508.                     end;
  509.         end;
  510.     
  511.     
  512.     Procedure DoSplatter(user:integer);
  513.         var
  514.             r                :rect;
  515.             i,xx,yy        :integer;
  516.             
  517.         begin
  518.             ClipRect(drect);
  519.             with UT[user] do
  520.                 for i := 1 to splatSpeed do
  521.                     begin
  522.                         repeat
  523.                             xx := random mod SplatRad;
  524.                             yy := random mod SplatRad;
  525.                         until xx*xx+yy*yy <= SplatRad*SplatRad;
  526.                         xx := xx + x;
  527.                         yy := yy + y;
  528.                         SetRect(r,xx,yy,xx+hSize,yy+vSize);
  529.                         PaintRect(r);
  530.                         OffBits;
  531.                         PaintRect(r);
  532.                         OnBits;
  533.                     end;
  534.             ClipRect(drawWindow^.portRect);
  535.         end;
  536.     
  537.     
  538.     Procedure DoRect(utnum:integer;r:rect;optDown:boolean);        { handle rect packets }
  539.         begin
  540.             Debug('DoRect');
  541.             with UT[utnum] do
  542.                 case theTool of
  543.                     TRect:    begin
  544.                                     if not optDown then
  545.                                         PenPat(black);
  546.                                     FrameRect(r);
  547.                                     OffBits;
  548.                                     FrameRect(r);
  549.                                     OnBits;
  550.                                 end;
  551.                     TFRect:    begin
  552.                                     PaintRect(r);
  553.                                     OffBits;
  554.                                     PaintRect(r);
  555.                                     OnBits;
  556.                                     if not optDown then
  557.                                         begin
  558.                                             PenPat(black);
  559.                                             FrameRect(r);
  560.                                             OffBits;
  561.                                             FrameRect(r);
  562.                                             OnBits;
  563.                                         end;
  564.                                 end;
  565.                     TOval:    begin
  566.                                     if not optDown then
  567.                                         PenPat(black);
  568.                                     FrameOval(r);
  569.                                     OffBits;
  570.                                     FrameOval(r);
  571.                                     OnBits;
  572.                                 end;
  573.                     TFOval:    begin
  574.                                     PaintOval(r);
  575.                                     OffBits;
  576.                                     PaintOval(r);
  577.                                     OnBits;
  578.                                     if not optDown then
  579.                                         begin
  580.                                             PenPat(black);
  581.                                             FrameOval(r);
  582.                                             OffBits;
  583.                                             FrameOval(r);
  584.                                             OnBits;
  585.                                         end;
  586.                                 end;
  587.                 end;
  588.         end;
  589.  
  590.  
  591.     Procedure DoDrag(utnum,dx,dy:integer);        { handle drag packets }
  592.         var
  593.             pt        :point;
  594.             r        :rect;
  595.             
  596.         begin
  597.             Debug('DoDrag');
  598.             with UT[utnum] do
  599.                 case theTool of
  600.                     Tbrush:    begin
  601.                                     if theMode=connect then
  602.                                         begin
  603.                                             GetPen(pt);
  604.                                             LineTo(dx,dy);
  605.                                             OffBits;
  606.                                             MoveTo(pt.h,pt.v);
  607.                                             LineTo(dx,dy);
  608.                                             OnBits;
  609.                                         end
  610.                                     else
  611.                                         begin
  612.                                             MoveTo(dx,dy);
  613.                                             Line(0,0);
  614.                                             OffBits;
  615.                                             MoveTo(dx,dy);
  616.                                             Line(0,0);
  617.                                             OnBits;
  618.                                         end;
  619.                                     x := dx;
  620.                                     y := dy;
  621.                                 end;
  622.                     Terase:    begin
  623.                                     penPat(white);
  624.                                     if theMode=connect then
  625.                                         begin
  626.                                             GetPen(pt);
  627.                                             LineTo(dx,dy);
  628.                                             OffBits;
  629.                                             MoveTo(pt.h,pt.v);
  630.                                             LineTo(dx,dy);
  631.                                             OnBits;
  632.                                         end
  633.                                     else
  634.                                         begin
  635.                                             MoveTo(dx,dy);
  636.                                             Line(0,0);
  637.                                             OffBits;
  638.                                             MoveTo(dx,dy);
  639.                                             Line(0,0);
  640.                                             OnBits;
  641.                                         end;
  642.                                     x := dx;
  643.                                     y := dy;
  644.                                 end;
  645.                     TSplatter:    begin
  646.                                         x := dx;
  647.                                         y := dy;
  648.                                         DoSplatter(utnum);
  649.                                     end;
  650.                 end;
  651.         end;
  652.     
  653.     
  654.     Procedure SendMyInfo(id:integer);    { send UT entry to node <id> }
  655.         begin
  656.             Debug('SendMyInfo');
  657.             with LAPwbuf do
  658.                 begin
  659.                     theType := sendinfo;
  660.                     info := UT[0];
  661.                 end;
  662.             SendLAP(id);
  663.         end;
  664.     
  665.     
  666.     Procedure DebugLAPType(t:MSGType);
  667.         begin
  668.             case t of
  669.                 paintMode:    Debug(' paintMode');
  670.                 alpha:        Debug(' alpha');
  671.                 settool:        Debug(' settool');
  672.                 eraseall:    Debug(' eraseall');
  673.                 setpat:        Debug(' setpat');
  674.                 setcolor:    Debug(' setcolor');
  675.                 setpen:        Debug(' setpen');
  676.                 setfont:        Debug(' setfont');
  677.                 setpos:        Debug(' setpos');
  678.                 drag:            Debug(' drag');
  679.                 rectpck:        Debug(' rect');
  680.                 rqinfo:        Debug(' rqinfo');
  681.                 sendinfo:    Debug(' sendinfo');
  682.             end;
  683.         end;
  684.     
  685.     
  686.     Procedure ExecMessage(var msg:LAPMsg);        { handle a LAP message }
  687.         var
  688.             j                :integer;
  689.             pt                :point;
  690.             savePort        :GrafPtr;
  691.             
  692.         begin
  693.             Debug('ExecMessage');
  694.             changed := true;
  695.             with msg do
  696.             if theType=rqInfo then                { handle rqInfo requests }
  697.                 begin
  698.                     SendMyInfo(id);
  699.                     DebugLAPType(theType);
  700.                 end
  701.             else                                        { handle graphics commands }
  702.                 begin
  703.                     GetPort(savePort);
  704.                     SetPort(DrawWindow);
  705.                     j := FindUser(id);                        { get index into user table }
  706.                     if j>=0 then
  707.                         begin
  708.                             SetUserState(j);                    { set user's port state }
  709.                             with UT[j] do
  710.                                 begin
  711.                                     DebugLAPType(theType);
  712.                                     case theType of
  713.                                         paintMode:    theMode := mode;
  714.                                         alpha:    begin
  715.                                                         GetPen(pt);
  716.                                                         DrawChar(ch);
  717.                                                         OffBits;
  718.                                                         MoveTo(pt.h,pt.v);
  719.                                                         DrawChar(ch);
  720.                                                         OnBits;
  721.                                                         GetPen(pt);
  722.                                                         x := pt.h;
  723.                                                         y := pt.v;
  724.                                                     end;
  725.                                         eraseall: begin
  726.                                                         eraseRect(drect);
  727.                                                         OffBits;
  728.                                                         eraseRect(drect);
  729.                                                         OnBits;
  730.                                                     end;
  731.                                         settool:    theTool := tool;
  732.                                         setpat:    thePat := pat;
  733.                                         setcolor:theClr := clr;
  734.                                         setpen:    begin
  735.                                                         hSize := px;
  736.                                                         vSize := py;
  737.                                                     end;
  738.                                         setfont:    begin
  739.                                                         theFnum := fnum;
  740.                                                         theFsize := fsize;
  741.                                                         theFstyle := fstyl;
  742.                                                     end;
  743.                                         setpos:    begin
  744.                                                         x := mx;
  745.                                                         y := my;
  746.                                                     end;
  747.                                         drag:    DoDrag(j,cx,cy);
  748.                                         rectpck:    DoRect(j,rct,optDown);
  749.                                         setSplat:    begin
  750.                                                             splatRad := sRad;
  751.                                                             splatSpeed := sSpeed;
  752.                                                         end;
  753.                                         sendinfo:    begin
  754.                                                             UT[j] := info;
  755.                                                             Debug(' sendInfo received');
  756.                                                         end;
  757.                                     end;
  758.                                     time := tickCount;        { user is active }
  759.                                 end;
  760.                         end
  761.                     else
  762.                         Debug(' msg not executed');
  763.                     SetPort(savePort);
  764.                 end;
  765.         end;
  766.     
  767.     
  768.     Procedure CheckQueue;        { execute packet commands from incoming queue }
  769.         var
  770.             msg        :LAPMsg;
  771.             
  772.         begin
  773.             if polling then
  774.                 CheckRead;
  775.             if xDequeue(msg) then        { incoming queue }
  776.                 ExecMessage(msg);
  777.         end;
  778.     
  779.     
  780.     Procedure SendLAP(who:byte);        { send a LAP Packet to node <id> }
  781.         var
  782.             sz        :longint;
  783.             
  784.         begin
  785.             Debug('SendLAP');
  786.             DebugLAPType(LAPwbuf.theType);
  787.             {   %%%%%%%%%% THIS NEEDS TO BE RECALCULATED! %%%%%%%%%%% }
  788.             case LAPwbuf.theType of
  789.                 paintMode,alpha,settool:    sz := 2;
  790.                 eraseall:                        sz := 0;
  791.                 setpat:                            sz := sizeof(pattern);
  792.                 setcolor:                        sz := sizeof(RGBColor);
  793.                 setfont:                            sz := sizeof(style) + 4;
  794.                 setpos,setpen,drag:            sz := 4;
  795.                 rectpck:                            sz := sizeof(rect)+2;
  796.                 sendinfo:                        sz := sizeof(UserTableRec);
  797.                 setSplat:                        sz := 4;
  798.             end;
  799.             sz := sizeof(MSGType)+4+sz;    { LAP packet size }
  800.             sz := sizeof(LAPMsg);            { <--- DEBUGGING ONLY }
  801.             with LAPwbuf do                    { set up LAP packet size, sender id }
  802.                 begin
  803.                     id := myNode;
  804.                     size[0] := sz div 256;
  805.                     size[1] := sz mod 256;
  806.                 end;
  807.             with LAPwh^^ do
  808.                 begin
  809.                     lapAddress.lapProtType := OurType;    { protocol type }
  810.                     lapAddress.dstNodeID := who;            { destination node }
  811.                     lapReqCount := sz;                        { packet size }
  812.                     lapDataPtr := @LAPwbuf;                    { packet data pointer }
  813.                 end;
  814.             err := LAPWrite(LAPwh,false);        { send LAP packet }
  815.             DoErr(70);
  816.             if LAPwbuf.theType < rqInfo then        { don't want to execute rqInfo or sendInfo locally }
  817.                 ExecMessage(LAPwbuf);    { execute message locally }
  818.         end;
  819.     
  820.     
  821.     Procedure CheckRead;
  822.         var
  823.             destnode        :integer;
  824.             
  825.         begin
  826.             SetUpA5;
  827.             err := LAPrh^^.abResult;
  828.             if err=0 then
  829.                 begin
  830.                     Debug('CheckRead: msg rcvd');
  831.                     DebugLAPType(LAPrbuf.theType);
  832.                     destNode := LAPrh^^.lapAddress.dstNodeID;
  833.                     if (destNode=255) or (destNode=myNode) then
  834.                         xEnqueue(LAPrbuf);
  835.                 end;
  836.             if err<>1 then
  837.                 begin
  838.                     with LAPrh^^ do
  839.                         begin
  840.                             lapAddress.lapProtType := OurType;
  841.                             lapReqCount := Sizeof(LAPMsg);
  842.                             lapDataPtr := @LAPrbuf;
  843.                         end;
  844.                     err := LAPRead(LAPrh,true);
  845.                     DoErr(5000);
  846.                 end;
  847.             myTask.vblCount := VBLCnt;
  848.             RestoreA5; 
  849.         end;    
  850.     
  851.     
  852.     Procedure SetUpRead;
  853.         begin
  854.             with LAPrh^^ do
  855.                 begin
  856.                     lapAddress.lapProtType := OurType;
  857.                     lapReqCount := Sizeof(LAPMsg);
  858.                     lapDataPtr := @LAPrbuf;
  859.                 end;
  860.             err := LAPRead(LAPrh,true);
  861.             DoErr(71);
  862.             if not polling then
  863.                 begin
  864.                     with myTask do
  865.                         begin
  866.                             qType := ord(vType);
  867.                             vblAddr := @CheckRead;
  868.                             vblCount := VBLCnt;
  869.                             vblPhase := VBLCnt div 2 + 1;
  870.                         end;
  871.                     err := VInstall(@myTask);
  872.                     DoErr(500);
  873.                 end;
  874.         end;
  875.     
  876.     
  877.     Procedure DisplayPatterns;
  878.         var
  879.             i        :integer;
  880.             
  881.         begin
  882.             for i := 1 to 8 do
  883.                 FillRect(toolRects[i+12],thePatterns[i]);
  884.             FillRect(curPatRect,thePatterns[curPat]);
  885.         end;
  886.         
  887.         
  888.     Procedure DisplayColors;
  889.         var
  890.             i        :integer;
  891.             
  892.         begin
  893.             PenNormal;
  894.             for i := 1 to 8 do
  895.                 begin
  896.                     RGBForeColor(theColors[i]);
  897.                     PaintRect(toolRects[i+12]);
  898.                 end;
  899.             RGBForeColor(theColors[curColor]);
  900.             PaintRect(curPatRect);
  901.         end;
  902.         
  903.         
  904.     Procedure DrawPalette;
  905.         var
  906.             r        :rect;
  907.             
  908.         begin
  909.             SetPort(DrawWindow);
  910.             DrawPicture(palette,prect);
  911.             with UT[0] do
  912.                 begin
  913.                     InvertRect(toolRects[theTool]);
  914.                     if not theMode then
  915.                         with toolRects[theTool] do
  916.                             begin
  917.                                 PenMode(PatXOR);
  918.                                 PenPat(ltgray);
  919.                                 PaintRect(toolRects[Tspray]);
  920.                                 PenNormal;
  921.                             end;
  922.                 end;
  923.             PenMode(PatXOR);
  924.             PenPat(ltgray);
  925.             if PatternsUp then
  926.                 begin
  927.                     PaintRect(toolRects[Tcolor]);
  928.                     PenNormal;
  929.                     DisplayPatterns;
  930.                 end
  931.             else
  932.                 begin
  933.                     PaintRect(toolRects[Tpat]);
  934.                     PenNormal;
  935.                     DisplayColors;
  936.                 end;
  937.             with vSizeRect,UT[0] do
  938.                 SetRect(r,left,top+(vSize-1)*2,right,top+vSize*2);
  939.             InvertRect(r);
  940.             with hSizeRect,UT[0] do
  941.                 SetRect(r,left,top+(hSize-1)*2,right,top+hSize*2);
  942.             InvertRect(r);
  943.             {
  944.                 draw current tools, modes, pattern/color, pensize
  945.             }
  946.         end;
  947.     
  948.     
  949.     Procedure OpenBitMap(r:rect);    { create offscreen bitmap }
  950.         var
  951.             pb                    :Bitmap;
  952.             xx,yy,sn            :Longint;
  953.             i                    :Integer;
  954.             saveGDevice        :GDHandle;
  955.             maxGDevice        :GDHandle;
  956.             theDepth            :Integer;
  957.             offRowBytes        :Longint;
  958.             sizeOfOff        :LongInt;
  959.             
  960.         begin
  961.             if MacII then
  962.                 begin
  963.                     if PixDraw then
  964.                         begin
  965.                             { * Pix Map Mak'in * }
  966.                             saveGDevice:=GetGDevice;
  967.                             maxGDevice:=GetMaxDevice(screenBits.Bounds);
  968.                             SetGDevice(maxGDevice);
  969.                             
  970.                             myCGrafPtr:=@myCGrafPort;
  971.                             OpenCPort(myCGrafPtr);
  972.                             theDepth:=myCGrafPtr^.portPixMap^^.pixelSize;
  973.                             
  974.                             with r do
  975.                                 begin
  976.                                     offRowBytes:=((((theDepth*(right-left))+15))DIV 16)*2;
  977.                                     sizeOfOff:=LongInt(bottom-top)*offRowBytes;
  978.                                 end;
  979.                             
  980.                             with myCGrafPtr^.portPixMap^^ do
  981.                                 begin
  982.                                     DisposPtr(baseAddr);
  983.                                     baseAddr:=NewPtr(sizeOfOff);
  984.                                     rowBytes:=offRowBytes+$8000;
  985.                                     bounds:=r;
  986.                                 end;
  987.                             
  988.                             ourCMHandle:=maxGDevice^^.gdpMap^^.pmTable;
  989.                             err:=HandToHand(handle(ourCMHandle));
  990.                             If Err<>NoErr then
  991.                                 SysBeep(1);
  992.                             
  993.                             {$R-}
  994.                             with ourCMHandle^^ do
  995.                                 begin
  996.                                     for i:=0 to ctSize do
  997.                                         ctTable[i].value:=i;
  998.                                     transIndex:=BAND(transIndex,$7FFF);
  999.                                 end;
  1000.                             {$R+}
  1001.                             
  1002.                             myCGrafPtr^.portPixMap^^.pmTable:=ourCMHandle;
  1003.                             
  1004.                             bmap:=BitMapPtr(myCGrafPtr^.portPixMap^)^;
  1005.                             Wbits:=BitMapPtr(CGrafPtr(DrawWindow)^.portPixMap^)^;
  1006.                             
  1007.                             SetPort(GrafPtr(myCGrafPtr));
  1008.                             EraseRect(thePort^.portRect);
  1009.                             
  1010.                             SetPort(DrawWindow);
  1011.                             SetGDevice(saveGDevice);
  1012.                         end;
  1013.                 end
  1014.             else
  1015.                 begin    
  1016.                     with r do
  1017.                         begin
  1018.                             xx := right-left;
  1019.                             yy := bottom-top;
  1020.                         end;
  1021.                     sn := ((xx+15) div 16)*2*yy;
  1022.                     with bmap do
  1023.                         begin
  1024.                             bounds := r;
  1025.                             rowBytes := ((xx+15) div 16)*2;
  1026.                             BaseAddr := NewPtr(sn);
  1027.                         end;
  1028.                     pb := DrawWindow^.portbits;
  1029.                     SetPortBits(bmap);
  1030.                     ClipRect(r);
  1031.                     RectRgn(DrawWindow^.visRgn,r);
  1032.                     EraseRect(r);
  1033.                     SetPortBits(pb);
  1034.                     ClipRect(DrawWindow^.portRect);
  1035.                     RectRgn(DrawWindow^.visRgn,DrawWindow^.portRect);
  1036.                     
  1037.                     Wbits:=DrawWindow^.portbits;
  1038.                 end;
  1039.         end;
  1040.     
  1041.     
  1042.     Procedure OpenDrawWindow;        { initialize drawing window }
  1043.         var
  1044.             r        :rect;
  1045.             
  1046.         begin
  1047.             if MacII then
  1048.                 DrawWindow := GetNewCWindow(129,nil,pointer(-1))
  1049.             else
  1050.                 DrawWindow := GetNewWindow(129,nil,pointer(-1));
  1051.             SetPort(DrawWindow);
  1052.             dRect := DrawWindow^.portrect;    { drawing area }
  1053.             drect.left := dRect.left + 46;    { make room for palette }
  1054.             setRect(r,0,0,576,720);
  1055.             OpenBitMap(r);
  1056.             prect := palette^^.picFrame;
  1057.             OffsetRect(prect,-prect.left,-prect.top);    { palette bounds }
  1058.             DrawPalette;
  1059.         end;
  1060.     
  1061.     
  1062.     Procedure ChangeTool(NewTool:Integer);        { set a new tool }
  1063.         begin
  1064.             with LAPwBuf do
  1065.                 begin
  1066.                     theType := setTool;
  1067.                     tool := NewTool;
  1068.                 end;
  1069.             SendLap(255);
  1070.         end;
  1071.         
  1072.         
  1073.     Function DoSizeTool(pt:point;r:rect;cur:integer):integer;
  1074.         var
  1075.             x            :integer;
  1076.             r2            :rect;
  1077.             
  1078.         begin
  1079.             repeat
  1080.                 x := (pt.v-r.top) div 2;
  1081.                 if x<1 then
  1082.                     x := 1
  1083.                 else if x>16 then
  1084.                     x := 16;
  1085.                 if x<>cur then
  1086.                     begin
  1087.                         SetRect(r2,r.left,r.top+(cur-1)*2,r.right,r.top+cur*2);
  1088.                         InvertRect(r2);
  1089.                         cur := x;
  1090.                         SetRect(r2,r.left,r.top+(cur-1)*2,r.right,r.top+cur*2);
  1091.                         InvertRect(r2);
  1092.                     end;
  1093.                 GetMouse(pt);
  1094.             until MyGetNextEvent(mUpMask,myEvent);
  1095.             DoSizeTool := cur;
  1096.         end;
  1097.         
  1098.     
  1099.     procedure PatternEditor(VAR myPat:Pattern);
  1100.         var
  1101.             dlg        :    DialogPtr;
  1102.             aPat        :    Pattern;
  1103.             myEvent    :    EventRecord;
  1104.             done        :    Boolean;
  1105.             draw        :    Boolean;
  1106.             dh,dv        :    Integer;
  1107.             
  1108.             patRect    :    Rect;
  1109.             patEdit    :    Rect;
  1110.             tRect        :    Rect;
  1111.             savePort    :    GrafPtr;
  1112.             
  1113.         function GetBitRect(index:Integer):Rect;
  1114.             begin
  1115.                 dh:=(index mod 8)*10;
  1116.                 dv:=(index Div 8)*10;
  1117.                 with tRect do
  1118.                     begin
  1119.                         left:=patEdit.left+dh;
  1120.                         right:=left+10;
  1121.                         top:=patEdit.top+dv;
  1122.                         bottom:=top+10;
  1123.                     end;
  1124.                 InsetRect(tRect,1,1);
  1125.                 GetBitRect:=tRect;
  1126.             end;
  1127.             
  1128.         procedure InitPatBits;
  1129.             var
  1130.                 i    :    Integer;
  1131.                 
  1132.             begin
  1133.                 for i:=0 to 63 do
  1134.                     if BitTst(@aPat,i)
  1135.                         then
  1136.                             FillRect(GetBitRect(i),Black)
  1137.                         else
  1138.                             FillRect(GetBitRect(i),White);
  1139.             end;
  1140.             
  1141.         function GetBitPos(pt:point):integer;
  1142.             begin
  1143.                 dh:=pt.h-patEdit.left;
  1144.                 dh:=dh div 10;
  1145.                 dv:=pt.v-patEdit.top;
  1146.                 dv:=dv div 10;
  1147.                 GetBitPos:=dv*8+dh;
  1148.             end;
  1149.             
  1150.         procedure EditPatClick(pt:point;firstOne:Boolean);
  1151.             var
  1152.                 index    :    integer;
  1153.                 
  1154.             begin
  1155.                 index:=GetBitPos(pt);
  1156.                 if firstOne then
  1157.                     begin
  1158.                         if BitTst(@aPat,index)
  1159.                             then
  1160.                                 draw:=false
  1161.                             else
  1162.                                 draw:=true;
  1163.                     end;
  1164.                 if draw
  1165.                     then
  1166.                         begin
  1167.                             FillRect(GetBitRect(index),Black);
  1168.                             BitSet(@aPat,index);
  1169.                         end
  1170.                     else
  1171.                         begin
  1172.                             FillRect(GetBitRect(index),White);
  1173.                             BitClr(@aPat,index);
  1174.                         end;
  1175.                 FillRect(patRect,aPat);
  1176.             end;
  1177.             
  1178.         begin
  1179.             GetPort(savePort);
  1180.             aPat:=myPat;
  1181.             dlg:=GetNewDialog(1000,Nil,Pointer(-1));
  1182.             HiliteButton(dlg);
  1183.             done:=false;
  1184.             GetDItem(dlg,3,iType,iTem,patEdit);
  1185.             tRect:=patEdit;
  1186.             InsetRect(tRect,-1,-1);
  1187.             FrameRect(tRect);
  1188.             GetDItem(dlg,4,iType,iTem,patRect);
  1189.             tRect:=patRect;
  1190.             InsetRect(tRect,-1,-1);
  1191.             FrameRect(tRect);
  1192.             FillRect(patRect,aPat);
  1193.             InitPatBits;
  1194.             Repeat
  1195.                 CheckQueue;
  1196.                 If MyGetNextEvent(everyEvent,myEvent) then
  1197.                     If isDialogEvent(myEvent) then
  1198.                         if DialogSelect(myEvent,myWindow,itemHit) then
  1199.                             Case itemHit of
  1200.                                 Ok,Cancel:Done:=True;
  1201.                                 3:
  1202.                                     with myEvent do
  1203.                                         begin
  1204.                                             GlobalToLocal(where);
  1205.                                             EditPatClick(where,true);
  1206.                                             Repeat
  1207.                                                 GetMouse(where);
  1208.                                                 if PtInRect(where,patEdit) then
  1209.                                                     EditPatClick(where,false);
  1210.                                                 CheckQueue;
  1211.                                             Until Not StillDown;
  1212.                                         end;
  1213.                             end;{Case}
  1214.             Until done;
  1215.             if ItemHit=Ok then
  1216.                 myPat:=aPat;
  1217.             DisposDialog(dlg);
  1218.             SetPort(savePort);
  1219.         end;
  1220.     
  1221.     
  1222.     Procedure SetupCursor;
  1223.         var
  1224.             savebits,bm        :bitmap;
  1225.             r                    :rect;
  1226.         begin
  1227.             with UT[0] do
  1228.                 case theTool of
  1229.                     Tbrush:    if MacII then
  1230.                                     begin
  1231.                                         SetCursor(arrow);    { * For now, should manipulate color cursor * }
  1232.                                     end
  1233.                                 else
  1234.                                     begin
  1235.                                         SetRect(bm.bounds,0,0,16,16);
  1236.                                         bm.baseAddr := @theCurs;
  1237.                                         bm.rowBytes := 2;
  1238.                                         saveBits := drawWindow^.portbits;
  1239.                                         SetPortBits(bm);
  1240.                                         EraseRect(bm.bounds);
  1241.                                         with UT[0] do
  1242.                                             SetRect(r,0,0,hSize,vSize);
  1243.                                         FillRect(r,black);
  1244.                                         SetPortBits(saveBits);
  1245.                                         SetCursor(theCurs);
  1246.                                     end;
  1247.                     TSplatter:    SetCursor(theSprayer^^);
  1248.                     Tletters:    SetCursor(GetCursor(iBeamCursor)^^);
  1249.                     Terase:    if MacII then
  1250.                                     begin
  1251.                                         SetCursor(arrow);    { * For now, should manipulate color cursor * }
  1252.                                     end
  1253.                                 else
  1254.                                     begin
  1255.                                         SetRect(bm.bounds,0,0,16,16);
  1256.                                         bm.baseAddr := @theECurs;
  1257.                                         bm.rowBytes := 2;
  1258.                                         saveBits := drawWindow^.portbits;
  1259.                                         SetPortBits(bm);
  1260.                                         FillRect(bm.bounds,white);
  1261.                                         with UT[0] do
  1262.                                             SetRect(r,0,0,hSize,vSize);
  1263.                                         FrameRect(r);
  1264.                                         bm.baseAddr := @theECurs.mask;
  1265.                                         EraseRect(bm.bounds);
  1266.                                         FillRect(r,black);
  1267.                                         SetPortBits(saveBits);
  1268.                                         SetCursor(theECurs);
  1269.                                     end;
  1270.                     Trect..Tfoval:    SetCursor(GetCursor(crossCursor)^^);
  1271.                 end;
  1272.             updateCurs := false;
  1273.         end;
  1274.     
  1275.     
  1276.     Procedure FixCursor;        { handle cursor updating }
  1277.         var
  1278.             pt        :point;
  1279.             
  1280.         begin
  1281.             If windowPeek(FrontWindow)^.windowKind>-1 then
  1282.                 begin
  1283.                     GetMouse(pt);
  1284.                     if (PtInRect(pt,dRect) and arrowCurs) or updateCurs then
  1285.                         begin
  1286.                             SetupCursor;
  1287.                             arrowCurs := false;
  1288.                         end
  1289.                     else if (not PtInRect(pt,dRect)) and (not arrowCurs) then
  1290.                         begin
  1291.                             SetCursor(arrow);
  1292.                             arrowCurs := true;
  1293.                         end;
  1294.                 end;
  1295.         end;
  1296.     
  1297.     
  1298.     Procedure SavePic(saveas:boolean);        { save file }
  1299.         var
  1300.             where            :point;
  1301.             reply            :SFReply;
  1302.             err            :integer;
  1303.             ar,dr            :packed array [0..75] of byte;
  1304.             n,l            :longint;
  1305.             i,j,ref        :integer;
  1306.             r,rr            :rect;
  1307.             bm                :bitmap;
  1308.             srcPtr        :ptr;
  1309.             dstPtr        :ptr;
  1310.             h                :handle;
  1311.             s                :str255;
  1312.             
  1313.         procedure ChkErr;
  1314.             begin
  1315.                 if err <> 0 then
  1316.                     DoErr(err);
  1317.             end;
  1318.             
  1319.         begin
  1320.             if not saved then
  1321.                 saveas := true;
  1322.             if saveas then
  1323.                 begin
  1324.                     SetPt(where,50,50);
  1325.                     GetWTitle(drawWindow,s);
  1326.                     SFPutFile(where,'Save document as:',s,@idleFilter,reply);
  1327.                     
  1328.                     BeginUpdate(DrawWindow);
  1329.                         DrawContents;
  1330.                         DrawPalette;
  1331.                     EndUpdate(DrawWindow);
  1332.                 end
  1333.             else
  1334.                 with reply do
  1335.                     begin
  1336.                         good := true;
  1337.                         GetWTitle(drawWindow,s);
  1338.                         fname := s;
  1339.                         vRefNum := fVref;
  1340.                     end;
  1341.             if reply.good then
  1342.                 begin
  1343.                     err := SetVol(nil,reply.vRefNum);
  1344.                     ChkErr;
  1345.                     if saveas then
  1346.                         begin
  1347.                             err := FSDelete(reply.fname,reply.vRefnum);
  1348.                             if (err<>noErr) and (err<>fnfErr) then
  1349.                                 ChkErr;
  1350.                             err := Create(reply.fname,reply.vRefnum,'JPNT','PNTG');
  1351.                             ChkErr;
  1352.                         end;
  1353.                     err := FSOpen(reply.fname,reply.vrefnum,ref);
  1354.                     ChkErr;
  1355.                     if saveas then
  1356.                         begin
  1357.                             err := SetEOF(ref,512);
  1358.                             ChkErr;
  1359.                             err := SetFPos(ref,fsFromStart,0);
  1360.                             ChkErr;
  1361.                             l := 0;
  1362.                             n := 4;
  1363.                             err := FSWrite(ref,n,@l);        { write version # 0 }
  1364.                             ChkErr;
  1365.                         end;
  1366.                     err := SetFPos(ref,fsFromStart,512);
  1367.                     ChkErr;
  1368.                     with bm do
  1369.                         begin
  1370.                             SetRect(bounds,0,0,72*8,1);
  1371.                             baseAddr := @ar;
  1372.                             rowbytes := 72;
  1373.                         end;
  1374.                     SetRect(rr,0,0,576,1);
  1375.                     for i := 0 to 719 do
  1376.                         begin
  1377.                             setRect(r,0,i,576,i+1);
  1378.                             CopyBits(bmap,bm,r,rr,SrcCopy,nil);
  1379.                             srcPtr := @ar;
  1380.                             dstPtr := @dr;
  1381.                             PackBits(srcPtr,dstPtr,72);
  1382.                             n := ord(dstPtr)-ord(@dr);
  1383.                             err := FSWrite(ref,n,@dr);
  1384.                             ChkErr;
  1385.                             CheckQueue;
  1386.                         end;
  1387.                     err := FSClose(ref);
  1388.                     ChkErr;
  1389.                     SetWTitle(drawWindow,reply.fname);
  1390.                     fVref := reply.vRefnum;
  1391.                     changed := false;
  1392.                     saved := true;
  1393.                 end;
  1394.         end;
  1395.     
  1396.     
  1397.     Function MySaveProc(dlg:DialogPtr;Var theEvent:EventRecord;VAR IH:Integer):Boolean;
  1398.         
  1399.         begin
  1400.             SetUpA5;
  1401.             MySaveProc:=false;
  1402.             CheckQueue;
  1403.             RestoreA5;
  1404.         end;
  1405.     
  1406.     
  1407.     Function Continue:Boolean;
  1408.         var
  1409.             choice    :    Integer;
  1410.         begin
  1411.             Continue:=true;
  1412.             If changed then
  1413.                 begin
  1414.                     choice:=NoteAlert(2000,@MySaveProc);
  1415.                     Case Choice of
  1416.                         2:    begin
  1417.                                 SavePic(false);
  1418.                                 If changed then
  1419.                                     Continue:=false;
  1420.                             end;
  1421.                         3:    Continue:=false;
  1422.                     end;
  1423.                 end;
  1424.         end;
  1425.     
  1426.     Procedure LoadPic;        { load picture }
  1427.         var
  1428.             where            :point;
  1429.             reply            :SFReply;
  1430.             err            :integer;
  1431.             ar                :packed array [0..75] of byte;
  1432.             n                :longint;
  1433.             i,j,ref        :integer;
  1434.             r,rr            :rect;
  1435.             bm                :bitmap;
  1436.             srcPtr,p        :ptr;
  1437.             dstPtr        :ptr;
  1438.             typeList        :SFTypeList;
  1439.  
  1440.         procedure ChkErr;
  1441.             begin
  1442.                 if err <> 0 then
  1443.                     DoErr(err);
  1444.             end;
  1445.             
  1446.         begin
  1447.             If not Continue then
  1448.                 exit(LoadPic);
  1449.             
  1450.             SetPt(where,80,50);
  1451.             typeList[0] := 'PNTG';
  1452.             SFGetFile(where,'Open document:',nil,1,typelist,@idleFilter,reply);
  1453.             if reply.good then
  1454.                 begin
  1455.                     BeginUpdate(DrawWindow);
  1456.                         DrawContents;
  1457.                         DrawPalette;
  1458.                     EndUpdate(DrawWindow);
  1459.                     
  1460.                     err := SetVol(nil,reply.vRefNum);
  1461.                     ChkErr;
  1462.                     err := FSOpen(reply.fname,reply.vrefnum,ref);
  1463.                     ChkErr;
  1464.                     err := SetFPos(ref,fsFromStart,512);
  1465.                     ChkErr;
  1466.                     with bm do
  1467.                         begin
  1468.                             SetRect(bounds,0,0,72*8,1);
  1469.                             baseAddr := @ar;
  1470.                             rowbytes := 72;
  1471.                         end;
  1472.                     err := GetEOF(ref,n);
  1473.                     ChkErr;
  1474.                     n := n-512;
  1475.                     p := NewPtr(n);
  1476.                     srcPtr := p;
  1477.                     err := FSRead(ref,n,srcPtr);
  1478.                     ChkErr;
  1479.                     SetRect(rr,0,0,576,1);
  1480.                     for i := 0 to 719 do
  1481.                         begin
  1482.                             dstPtr := @ar;
  1483.                             UnPackBits(srcPtr,dstPtr,72);
  1484.                             setRect(r,0,i,576,i+1);
  1485.                             CopyBits(bm,bmap,rr,r,SrcCopy,nil);
  1486.                             CheckQueue;
  1487.                         end;
  1488.                     disposPtr(p);
  1489.                     err := FSClose(ref);
  1490.                     ChkErr;
  1491.                     SetWTitle(drawWindow,reply.fname);
  1492.                     fVref := reply.vRefnum;
  1493.                     changed := false;
  1494.                     saved := true;
  1495.                     InvalRect(drect);
  1496.                 end;
  1497.         end;
  1498.     
  1499.     
  1500.     Procedure FadeIn(r:rect;pat:pattern);
  1501.         var
  1502.             v,h,x,i,n        :longint;
  1503.             
  1504.         begin
  1505.             pennormal;
  1506.             penpat(pat);
  1507.             with r do
  1508.                 begin
  1509.                     v := bottom-top;
  1510.                     h := right-left;
  1511.                     for x := 1 to h do
  1512.                         begin
  1513.                             n := (x*v) div h;
  1514.                             for i := 1 to n do
  1515.                                 begin
  1516.                                     moveto(x+left,top+(i*v) div n);
  1517.                                     line(0,0);
  1518.                                 end;
  1519.                         end;
  1520.                 end;
  1521.         end;
  1522.  
  1523.  
  1524.     Procedure FadeOut(r:rect;pat:pattern);
  1525.         var
  1526.             v,h,x,i,n        :longint;
  1527.             
  1528.         begin
  1529.             pennormal;
  1530.             penpat(pat);
  1531.             with r do
  1532.                 begin
  1533.                     v := bottom-top;
  1534.                     h := right-left;
  1535.                     for x := 1 to h do
  1536.                         begin
  1537.                             n := ((h-x)*v) div h;
  1538.                             for i := 1 to n do
  1539.                                 begin
  1540.                                     moveto(x+left,top+(i*v) div n);
  1541.                                     line(0,0);
  1542.                                 end;
  1543.                         end;
  1544.                 end;
  1545.         end;
  1546.  
  1547.  
  1548.     Procedure FadeInto(r:rect;inPat,outPat:pattern);
  1549.         begin
  1550.             SysBeep(1);
  1551.         end;
  1552.  
  1553.     
  1554.     Procedure PastePicture;
  1555.         var
  1556.             PPHdl        :    Handle;            { * Paste Picture handle * }
  1557.             PTHdl        :    Handle;            { * Paste TEXT handle * }
  1558.             Sclen        :    Longint;
  1559.             offset    :    Longint;
  1560.             anEvent    :    EventRecord;
  1561.             PicRect    :    Rect;
  1562.             err        :    Longint;
  1563.             info        :    FontInfo;
  1564.             TEXTStr    :    Str255;
  1565.             TBox        :    Rect;
  1566.         begin
  1567.             err:=LoadScrap;
  1568.             PPHdl:=NewHandle(0);
  1569.             Sclen:=GetScrap(PPHdl,'PICT',offset);
  1570.             If Sclen<0 then
  1571.                 begin
  1572.                     PTHdl:=NewHandle(0);
  1573.                     Sclen:=GetScrap(PTHdl,'TEXT',offset);
  1574.                     If Sclen>-1 then
  1575.                         begin
  1576.                             GetFontInfo(info);
  1577.                             GetiText(PTHdl,TEXTStr);
  1578.                             with DrawWindow^.portRect,info do
  1579.                                 SetRect(TBox,left,top,left+StringWidth(TEXTStr)+1,top+ascent+descent+leading);
  1580.                             HLock(PTHdl);
  1581.                             PPHdl:=Handle(OpenPicture(TBox));
  1582.                             TextBox(PTHdl^,Sclen,TBox,teJustLeft);
  1583.                             ClosePicture;
  1584.                             HunLock(PTHdl);
  1585.                         end;
  1586.                     DisposHandle(PTHdl);
  1587.                 end;
  1588.             If Sclen>-1 then
  1589.                 begin
  1590.                     SetCursor(ThePlacer^^);
  1591.                     
  1592.                     Repeat
  1593.                         CheckQueue;
  1594.                     Until MyGetNextEvent(mDownmask,anEvent);
  1595.                     
  1596.                     with anEvent do
  1597.                         begin
  1598.                             GlobalToLocal(where);
  1599.                             If (what=mouseDown) & (PtinRect(where,DrawWindow^.portRect) & not (PtInRect(where,prect))) then
  1600.                                 with PicHandle(PPHdl)^^.picFrame,where do
  1601.                                     begin
  1602.                                         ClipRect(dRect);
  1603.                                         SetRect(PicRect,h,v,h+(right-left),v+(bottom-top));
  1604.                                         DrawPicture(PicHandle(PPHdl),PicRect);
  1605.                                         OffBits;
  1606.                                         DrawPicture(PicHandle(PPHdl),PicRect);
  1607.                                         OnBits;
  1608.                                         ClipRect(DrawWindow^.portRect);
  1609.                                     end;
  1610.                         end;
  1611.                     updateCurs:=true;
  1612.                 end;
  1613.             DisposHandle(PPHdl);
  1614.         end;
  1615.     
  1616.     
  1617.     Procedure ResizeSprayKan;
  1618.     
  1619.     var
  1620.         ResizeBox    :    Rect;
  1621.         CircleBox    :    Rect;
  1622.         savePort        :    GrafPtr;
  1623.         pt                :    Point;
  1624.         tStr            :    Str255;
  1625.         x,y            :    Integer;
  1626.         newRad        :    Integer;
  1627.         newSpeed        :    Integer;
  1628.         sr                :    Integer;    { * Save radius * }
  1629.         
  1630.         procedure ShowSize(where:Point);
  1631.         
  1632.         var
  1633.             dx,dy,dd    :    Integer;
  1634.         
  1635.         begin
  1636.             with where do
  1637.                 begin
  1638.                     dx:=abs(x-h);
  1639.                     dy:=abs(y-v);
  1640.                 end;
  1641.             If dx>dy
  1642.                 then
  1643.                     dd:=dx
  1644.                 else
  1645.                     dd:=dy;
  1646.             If dd<sr then
  1647.                 EraseRect(ResizeBox);
  1648.             sr:=dd;
  1649.                 
  1650.             SetRect(CircleBox,x-dd,y-dd,x+dd,y+dd);
  1651.             FillOval(CircleBox,Black);
  1652.             
  1653.             newRad:=dd;
  1654.         end;
  1655.         
  1656.     begin
  1657.         GetPort(savePort);
  1658.         Dlg:=GetNewDialog(1001,Nil,Pointer(-1));
  1659.         HiliteButton(Dlg);
  1660.         
  1661.         SetCursor(theSizer^^);
  1662.         newRad:=UT[0].splatRad;
  1663.         
  1664.         PenNormal;
  1665.         GetDItem(Dlg,5,iType,iTem,Box);
  1666.         newSpeed:=UT[0].splatSpeed;
  1667.         SetiText(iTem,Str(newSpeed));
  1668.         SeliText(Dlg,5,0,255);
  1669.         
  1670.         GetDItem(Dlg,3,iType,iTem,Box);
  1671.         ResizeBox:=Box;
  1672.         InsetRect(Box,-1,-1);
  1673.         FrameRect(Box);
  1674.         
  1675.         sr:=newRad;
  1676.         with ResizeBox do
  1677.             begin
  1678.                 x:=left+(right-left) Div 2;
  1679.                 y:=top+(bottom-top) Div 2;
  1680.                 SetRect(CircleBox,x-sr,y-sr,x+sr,y+sr);
  1681.             end;
  1682.         FillOval(CircleBox,Black);
  1683.         
  1684.         ItemHit:=0;
  1685.         Repeat
  1686.             CheckQueue;
  1687.             If MyGetNextEvent(everyEvent,myEvent) then
  1688.                 If isDialogEvent(myEvent) then
  1689.                     if DialogSelect(myEvent,Dlg,itemHit) then
  1690.                         Case itemHit of
  1691.                             ok:    begin
  1692.                                         GetDItem(Dlg,5,iType,iTem,Box);
  1693.                                         GetiText(iTem,tStr);
  1694.                                         newSpeed:=Val(tStr);
  1695.                                         If newSpeed<1
  1696.                                             then
  1697.                                                 begin
  1698.                                                     SysBeep(1);
  1699.                                                     newSpeed:=1;
  1700.                                                 end
  1701.                                             else if newSpeed>255 then
  1702.                                                 begin
  1703.                                                     SysBeep(1);
  1704.                                                     newSpeed:=255;
  1705.                                                 end;
  1706.                                     end;
  1707.                             3:    with myEvent do
  1708.                                     begin
  1709.                                         GlobalToLocal(where);
  1710.                                         pt:=where;
  1711.                                         ShowSize(where);
  1712.                                         Repeat
  1713.                                             GetMouse(where);
  1714.                                             If PtinRect(where,ResizeBox) then
  1715.                                                 If longInt(where)<>longInt(pt) then
  1716.                                                     begin
  1717.                                                         ShowSize(where);
  1718.                                                         pt:=where;
  1719.                                                     end;
  1720.                                             CheckQueue;
  1721.                                         Until Not StillDown;
  1722.                                     end;
  1723.                         end; { case }
  1724.         Until ItemHit in [ok,cancel];
  1725.         
  1726.         If ItemHit=ok then
  1727.             begin
  1728.                 with LAPwbuf do
  1729.                     begin
  1730.                         theType := setSplat;
  1731.                         sRad := newRad;
  1732.                         sSpeed := newSpeed;
  1733.                     end;
  1734.                 SendLAP(255);
  1735.             end;
  1736.             
  1737.         DisposDialog(Dlg);
  1738.         SetPort(savePort);
  1739.     end;
  1740.     
  1741.     
  1742.     Procedure ToolClick(pt:point);
  1743.         
  1744.         var
  1745.             i,a,h,v            :integer;
  1746.             dblClick            :boolean;
  1747.             where                :point;
  1748.             outColor            :RGBColor;
  1749.             
  1750.         begin
  1751.             dblClick := (TickCount-clickTime<GetDblTime);    { possible double click? }
  1752.             clickTime := TickCount;
  1753.             a := 0;
  1754.             for i := 1 to 20 do
  1755.                 if ptInRect(pt,toolRects[i]) then
  1756.                     begin
  1757.                         a := i;
  1758.                         leave;
  1759.                     end;
  1760.             dblClick:=(a=lastTool) and dblClick;
  1761.             if a>0 then
  1762.                 begin
  1763.                     lastTool := a;
  1764.                     case a of
  1765.                         1:    begin                                                { spray can }
  1766.                                 with LAPwbuf do
  1767.                                     begin
  1768.                                         theType := paintMode;
  1769.                                         mode := not UT[0].theMode;
  1770.                                     end;
  1771.                                 SendLAP(255);
  1772.                                 PenMode(PatXOR);
  1773.                                 PenPat(ltgray);
  1774.                                 PaintRect(toolRects[Tspray]);
  1775.                                 PenNormal;
  1776.                             end;
  1777.                         2..9:    if dblClick then
  1778.                                     case a of
  1779.                                         TErase:    begin
  1780.                                                         LAPwbuf.theType := eraseall;
  1781.                                                         SendLAP(255);
  1782.                                                     end;
  1783.                                         TSplatter:
  1784.                                                     ResizeSprayKan;
  1785.                                     end
  1786.                                 else
  1787.                                     with UT[0] do                                { Handle new tools }
  1788.                                         if theTool<>a then
  1789.                                             begin
  1790.                                                 InvertRect(ToolRects[theTool]);
  1791.                                                 InvertRect(ToolRects[a]);
  1792.                                                 ChangeTool(a);
  1793.                                             end;
  1794.                         10:    begin        { disk icon }
  1795.                                 end;
  1796.                         11,12:    if (PatternsUp<>(a=11)) and MacII then                { pattern/color switch }
  1797.                                         begin    
  1798.                                             PenMode(PatXOR);
  1799.                                             PenPat(ltgray);
  1800.                                             PaintRect(toolRects[Tpat]);
  1801.                                             PaintRect(toolRects[Tcolor]);
  1802.                                             PenNormal;
  1803.                                             PatternsUp := not PatternsUp;
  1804.                                             if PatternsUp then
  1805.                                                 DisplayPatterns
  1806.                                             else
  1807.                                                 DisplayColors;
  1808.                                         end
  1809.                                     else if PatternsUp<>(a=11) then
  1810.                                         sysbeep(1);
  1811.                         13..20:    if dblClick then
  1812.                                         begin
  1813.                                             if patternsUp then
  1814.                                                 begin    
  1815.                                                     PatternEditor(thePatterns[a-12]);
  1816.                                                     with LAPwbuf do
  1817.                                                         begin
  1818.                                                             theType := setpat;
  1819.                                                             pat := thePatterns[a-12];
  1820.                                                         end;
  1821.                                                     SendLAP(255);
  1822.                                                     curPat := a-12;
  1823.                                                     DisplayPatterns;
  1824.                                                 end
  1825.                                             else
  1826.                                                 begin
  1827.                                                     { color picker }
  1828.                                                     SetPt(where,0,0);    { * The color picker will center itself * }
  1829.                                                     if GetColor(where,'Set Pallete color to:',theColors[a-12],outColor) then
  1830.                                                         begin
  1831.                                                             theColors[a-12]:=outColor;
  1832.                                                             with LAPwbuf do
  1833.                                                                 begin
  1834.                                                                     theType := setcolor;
  1835.                                                                     clr := outColor;
  1836.                                                                 end;
  1837.                                                             SendLAP(255);
  1838.                                                         end;
  1839.                                                     curColor := a-12;
  1840.                                                     DisplayColors;
  1841.                                                 end;
  1842.                                         end
  1843.                                     else        { single click }
  1844.                                         begin
  1845.                                             if PatternsUp and (curPat<>a-12) then        { pattern/color selection }
  1846.                                                 begin
  1847.                                                     with LAPwbuf do
  1848.                                                         begin
  1849.                                                             theType := setpat;
  1850.                                                             pat := thePatterns[a-12];
  1851.                                                         end;
  1852.                                                     SendLAP(255);
  1853.                                                     curPat := a-12;
  1854.                                                     FillRect(curPatRect,thePatterns[curPat]);
  1855.                                                 end
  1856.                                             else if not(patternsUp) and (curColor<>a-12) then
  1857.                                                 begin
  1858.                                                     with LAPwbuf do
  1859.                                                         begin
  1860.                                                             theType := setcolor;
  1861.                                                             clr := theColors[a-12];
  1862.                                                         end;
  1863.                                                     SendLAP(255);
  1864.                                                     curColor := a-12;
  1865.                                                     RGBForeColor(theColors[curColor]);
  1866.                                                     PaintRect(curPatRect);
  1867.                                                 end;
  1868.                                         end;
  1869.                     end;
  1870.                     updateCurs := true;
  1871.                 end
  1872.             else if PtInRect(pt,hSizeRect) then
  1873.                 begin
  1874.                     v := UT[0].vSize;
  1875.                     h := DoSizeTool(pt,hSizeRect,UT[0].hSize);
  1876.                     with LAPwbuf do
  1877.                         begin
  1878.                             theType := setPen;
  1879.                             px := h;
  1880.                             py := v;
  1881.                         end;
  1882.                     SendLAP(255);
  1883.                     updateCurs:=true;
  1884.                 end
  1885.             else if PtInRect(pt,vSizeRect) then
  1886.                 begin
  1887.                     h := UT[0].hSize;
  1888.                     v := DoSizeTool(pt,vSizeRect,UT[0].vSize);
  1889.                     with LAPwbuf do
  1890.                         begin
  1891.                             theType := setPen;
  1892.                             px := h;
  1893.                             py := v;
  1894.                         end;
  1895.                     SendLAP(255);
  1896.                     updateCurs := true;
  1897.                 end;
  1898.         end;
  1899.     
  1900.     Function Sgn(i:integer):integer;
  1901.         begin
  1902.             if i<0 then
  1903.                 sgn := -1
  1904.             else if i>0 then
  1905.                 sgn := 1
  1906.             else
  1907.                 sgn := 0;
  1908.         end;
  1909.     
  1910.     
  1911.     Procedure MakeRect(pt1:point);
  1912.         var
  1913.             LastPt,pt        :point;
  1914.             x,y                :integer;
  1915.             dx,dy                :integer;
  1916.             r                    :rect;
  1917.             
  1918.         begin
  1919.             lastPt := pt1;
  1920.             with pt1 do
  1921.                 begin
  1922.                     x := h;
  1923.                     y := v;
  1924.                 end;
  1925.             Repeat
  1926.                 GetMouse(Pt);
  1927.                 if pt.h>drect.right then        { pin mouse inside drect }
  1928.                     pt.h := drect.right
  1929.                 else if pt.h<drect.left then
  1930.                     pt.h := drect.left;
  1931.                 if pt.v>drect.bottom then
  1932.                     pt.v := drect.bottom
  1933.                 else if pt.v<drect.top then
  1934.                     pt.v := drect.top;
  1935.                 if longint(LastPt)<>longint(pt) then    { mouse moved } { NOTE: this is faster than EqualPt }
  1936.                     begin
  1937.                         { --- erase old rect --- }
  1938.                         SetRect(r,x,y,LastPt.h,LastPt.v);
  1939.                         if x>LastPt.h then
  1940.                             begin
  1941.                                 r.left := LastPt.h;
  1942.                                 r.right := x;
  1943.                             end;
  1944.                         if y>LastPt.v then
  1945.                             begin
  1946.                                 r.top := LastPt.v;
  1947.                                 r.bottom := y;
  1948.                             end;
  1949.                         CopyBits(bmap,Wbits,r,r,srcCopy,nil);    { flicker-matic quick fix }
  1950.                         { --- check for shift constraint --- }
  1951.                         if bitAnd(mods,shiftKey)<>0 then
  1952.                             begin
  1953.                                 dx := abs(pt.h-pt1.h);
  1954.                                 dy := abs(pt.v-pt1.v);
  1955.                                 if dy<dx then
  1956.                                     pt.h := pt1.h + dy*sgn(pt.h-pt1.h)
  1957.                                 else
  1958.                                     pt.v := pt1.v + dx*sgn(pt.v-pt1.v);
  1959.                             end;
  1960.                         { --- calculate new rect --- }
  1961.                         SetRect(r,x,y,pt.h,pt.v);
  1962.                         if x>pt.h then
  1963.                             begin
  1964.                                 r.left := pt.h;
  1965.                                 r.right := x;
  1966.                             end;
  1967.                         if y>pt.v then
  1968.                             begin
  1969.                                 r.top := pt.v;
  1970.                                 r.bottom := y;
  1971.                             end;
  1972.                         { --- fix mistakes --- }
  1973.                         with UT[0] do            { set my user state cuz checkqueue screws it up }
  1974.                             begin
  1975.                                 PenPat(thePat);
  1976.                                 if MacII then
  1977.                                     RGBForeColor(theClr);
  1978.                                 PenSize(hSize,vSize);
  1979.                             end;
  1980.                         { --- draw rect --- }
  1981.                         case UT[0].theTool of
  1982.                             TRect:    begin
  1983.                                             if bitAnd(mods,optionKey)=0 then
  1984.                                                 PenPat(black);
  1985.                                             FrameRect(r);
  1986.                                         end;
  1987.                             TFRect:    begin
  1988.                                             PaintRect(r);
  1989.                                             if bitAnd(mods,optionKey)=0 then
  1990.                                                 begin
  1991.                                                     PenPat(black);
  1992.                                                     FrameRect(r);
  1993.                                                 end;
  1994.                                         end;
  1995.                             TOval:    begin
  1996.                                             if bitAnd(mods,optionKey)=0 then
  1997.                                                 PenPat(black);
  1998.                                             FrameOval(r);
  1999.                                         end;
  2000.                             TFOval:    begin
  2001.                                             PaintOval(r);
  2002.                                             if bitAnd(mods,optionKey)=0 then
  2003.                                                 begin
  2004.                                                     PenPat(black);
  2005.                                                     FrameOval(r);
  2006.                                                 end;
  2007.                                         end;
  2008.                         end;
  2009.                     end;
  2010.                 LastPt := pt;
  2011.                 CheckQueue;
  2012.             Until MyGetNextEvent(mupmask,myEvent);
  2013.             
  2014.             with LAPwbuf do
  2015.                 begin
  2016.                     theType := rectpck;        { send rectpck packet }
  2017.                     rct := r;
  2018.                     optDown := (bitAnd(mods,optionKey)<>0);
  2019.                 end;
  2020.             SendLAP(255);                    { send message to everyone }
  2021.         end;
  2022.     
  2023.     
  2024.     Procedure MasterClick(pt:Point);        { handle mouseDown events in our window }
  2025.         var
  2026.             LastPt            :Point;
  2027.             dx,dy                :integer;
  2028.             mypart            :integer;
  2029.             
  2030.         begin
  2031.             { * If a DA then get of of here * }
  2032.             if windowPeek(FrontWindow)^.windowKind<0 then
  2033.                 exit(MasterClick);
  2034.             
  2035.             if PtInRect(pt,prect) then        { click in palette }
  2036.                 ToolClick(pt)
  2037.             else
  2038.                 begin
  2039.                     if UT[0].theTool in [TRect..TFOval] then
  2040.                         MakeRect(pt)
  2041.                     else
  2042.                         begin
  2043.                             with LAPwbuf do
  2044.                                 begin
  2045.                                     theType := setpos;        { send setpos packet }
  2046.                                     mx := pt.h;
  2047.                                     my := pt.v;
  2048.                                 end;
  2049.                             SendLAP(255);        { send setpos packet to everyone }
  2050.                             Repeat
  2051.                                 GetMouse(Pt);
  2052.                                 if pt.h>drect.right then        { pin mouse inside drect }
  2053.                                     pt.h := drect.right
  2054.                                 else if pt.h<drect.left then
  2055.                                     pt.h := drect.left;
  2056.                                 if pt.v>drect.bottom then
  2057.                                     pt.v := drect.bottom
  2058.                                 else if pt.v<drect.top then
  2059.                                     pt.v := drect.top;
  2060.                                 if (longint(LastPt)<>longint(Pt)) | (UT[0].TheTool=Tsplatter) then        { mouse moved } { NOTE: this is faster than EqualPt }
  2061.                                     begin
  2062.                                         with LAPwbuf do
  2063.                                             begin
  2064.                                                 theType := drag;        { send drag packet }
  2065.                                                 cx := pt.h;
  2066.                                                 cy := pt.v;
  2067.                                             end;
  2068.                                         SendLAP(255);                    { send message to everyone }
  2069.                                         LastPt := Pt;
  2070.                                     end;
  2071.                                 CheckQueue;
  2072.                             Until MyGetNextEvent(mupmask,myevent);
  2073.                         end;
  2074.                 end;
  2075.         end;
  2076.     
  2077.     
  2078.     Procedure MasterKey(theChar:char);
  2079.         begin
  2080.             if UT[0].theTool = Tletters then
  2081.                 if theChar>=' ' then
  2082.                     begin
  2083.                         with LAPwbuf do
  2084.                             begin
  2085.                                 theType := alpha;
  2086.                                 ch := theChar;
  2087.                             end;
  2088.                         SendLAP(255);
  2089.                     end;
  2090.         end;
  2091.     
  2092.     
  2093.     Procedure ChangeFont;
  2094.         var
  2095.             s        :str255;
  2096.             i        :integer;
  2097.         begin
  2098.             CheckItem(myMenus[fontMenu],theFontidx,false);
  2099.             theFontidx:=theItem;
  2100.             GetItem(mymenus[fontMenu],theItem,s);
  2101.             GetFNum(s,theItem);
  2102.             CheckItem(myMenus[fontMenu],theFontidx,true);
  2103.             with UT[0] do
  2104.                 if theItem<>theFNum then
  2105.                     begin
  2106.                         with LAPwbuf do
  2107.                             begin
  2108.                                 theType := setfont;
  2109.                                 fnum := theItem;
  2110.                                 fsize := theFSize;
  2111.                                 fstyl := theFstyle;
  2112.                             end;
  2113.                         SendLAP(255);
  2114.                     end;
  2115.             for i:=1 to 9 do
  2116.                 begin
  2117.                     GetItem(myMenus[sizeMenu],i,s);
  2118.                     if RealFont(theItem,Val(s))
  2119.                         then
  2120.                             SetItemStyle(myMenus[sizeMenu],i,[Outline])
  2121.                         else
  2122.                             SetItemStyle(myMenus[sizeMenu],i,[]);
  2123.                 end;
  2124.         end;
  2125.     
  2126.     
  2127.         procedure ChangeStyle;
  2128.             const
  2129.                 plainItem    =    1;
  2130.             
  2131.             var
  2132.                 markChar        :char;
  2133.                 StyleArray    :packed array [1..7] of styleitem;
  2134.                 i                :integer;
  2135.                 CStyle        :style;
  2136.             
  2137.             begin
  2138.                 CStyle:=UT[0].theFStyle;
  2139.                 StyleArray[1]:=Bold;
  2140.                 StyleArray[2]:=Italic;
  2141.                 StyleArray[3]:=Underline;
  2142.                 StyleArray[4]:=Outline;
  2143.                 StyleArray[5]:=Shadow;
  2144.                 StyleArray[6]:=Extend;
  2145.                 StyleArray[7]:=Condense;
  2146.                 If theitem=plainItem then
  2147.                     begin
  2148.                         CheckItem(myMenus[styleMenu],1,true);
  2149.                         for i:=2 to 8 do
  2150.                             CheckItem(myMenus[styleMenu],i,false);
  2151.                         CStyle:=[];
  2152.                     end
  2153.                 else
  2154.                     begin
  2155.                         CheckItem(myMenus[styleMenu],1,false);
  2156.                         GetItemMark(myMenus[styleMenu],theitem,markChar);
  2157.                         If markChar=chr(noMark) then
  2158.                             begin
  2159.                                 CStyle:=CStyle+[StyleArray[theitem-1]];
  2160.                                 CheckItem(myMenus[styleMenu],theitem,True);
  2161.                             end
  2162.                         else
  2163.                             begin
  2164.                                 CheckItem(myMenus[styleMenu],theitem,false);
  2165.                                 CStyle:=CStyle-[StyleArray[theitem-1]];
  2166.                                 If CStyle=[] then
  2167.                                     CheckItem(myMenus[styleMenu],1,true);
  2168.                             end;
  2169.                     end;
  2170.                 if CStyle<>UT[0].theFStyle then
  2171.                     begin
  2172.                         with LAPwbuf do
  2173.                             begin
  2174.                                 theType := setfont;
  2175.                                 with UT[0] do
  2176.                                     begin
  2177.                                         fNum := theFNum;
  2178.                                         fSize := theFSize;
  2179.                                         fStyl := CStyle;
  2180.                                     end;
  2181.                             end;
  2182.                         SendLAP(255);
  2183.                     end;
  2184.             end;
  2185.  
  2186.  
  2187.     Procedure ChangeSize;
  2188.         var
  2189.             s        :str255;
  2190.             
  2191.         begin
  2192.             if theSizeidx<>theItem then
  2193.                 begin
  2194.                     CheckItem(myMenus[sizeMenu],theSizeidx,false);
  2195.                     CheckItem(myMenus[sizeMenu],theItem,true);
  2196.                     theSizeidx:=theItem;
  2197.                     GetItem(mymenus[sizeMenu],theItem,s);
  2198.                     theItem:=Val(s);
  2199.                     with UT[0] do
  2200.                         begin
  2201.                             with LAPwbuf do
  2202.                                 begin
  2203.                                     theType := setfont;
  2204.                                     fnum := theFNum;
  2205.                                     fsize := theItem;
  2206.                                     fstyl := theFstyle;
  2207.                                 end;
  2208.                             SendLAP(255);
  2209.                         end;
  2210.                 end;
  2211.         end;
  2212.     
  2213.     
  2214.     Procedure DrawContents;    { redraw drawing }
  2215.         begin
  2216.             SetPort(DrawWindow);
  2217.             CopyBits(bmap,wbits,drect,drect,SrcCopy,Nil);
  2218.         end;
  2219.     
  2220.     
  2221.     Procedure PrintPic;        { print a document }
  2222.         var
  2223.             GetOutEh        :    Boolean;
  2224.             temphPrint    :    THPrint;
  2225.             err            :    OSErr;
  2226.             savePort        :    GrafPtr;
  2227.             myPrPort        :    TPPrPort;
  2228.             myStRec        :    TPrStatus;
  2229.             i                :    Integer;
  2230.             
  2231.         begin
  2232.             temphPrint:=hPrint;
  2233.             err:=HandToHand(handle(temphPrint));
  2234.             if Err<>NoErr then
  2235.                 begin
  2236.                     SysBeep(1);
  2237.                     exit(PrintPic);
  2238.                 end;
  2239.             
  2240.             PrOpen;
  2241.             if PrJobDialog(temphPrint)
  2242.                 then
  2243.                     begin
  2244.                         GetOutEh:=false;
  2245.                         DisposHandle(handle(hPrint));
  2246.                         If MemError<>NoErr then
  2247.                             SysBeep(1);
  2248.                         
  2249.                         hPrint:=temphPrint;
  2250.                         err:=HandToHand(handle(hPrint));
  2251.                         If Err<>NoErr then
  2252.                             begin
  2253.                                 SysBeep(1);
  2254.                                 GetOutEh:=true;
  2255.                             end;
  2256.                     end
  2257.                 else
  2258.                     GetOutEh:=true;
  2259.             PrClose;
  2260.             
  2261.             DisposHandle(handle(temphPrint));
  2262.             if GetOutEh then
  2263.                 exit(PrintPic);
  2264.             
  2265.             BeginUpdate(DrawWindow);
  2266.                 DrawContents;
  2267.                 DrawPalette;
  2268.             EndUpdate(DrawWindow);
  2269.             
  2270.             GetPort(savePort);
  2271.             for i:=1 to hPrint^^.PrJob.iCopies do
  2272.                 begin
  2273.                     PrOpen;
  2274.                         If PrError=noErr then
  2275.                             begin
  2276.                                 myPrPort:=PrOpenDoc(hPrint,Nil,Nil);
  2277.                                 If PrError=noErr then
  2278.                                     begin
  2279.                                         PrOpenPage(myPrPort,Nil);
  2280.                                         If PrError=noErr then
  2281.                                             CopyBits(bmap,myPrPort^.gPort.portBits,bmap.bounds,bmap.bounds,SrcCopy,Nil);
  2282.                                         PrClosePage(myPrPort);
  2283.                                     end;
  2284.                             end;
  2285.                     If PrError=noErr then
  2286.                         PrCloseDoc(myPrPort);
  2287.                     If (hPrint^^.prJob.bjDocLoop=bSpoolLoop) and (PrError=NoErr) then
  2288.                         PrPicFile(hPrint,Nil,Nil,Nil,myStRec);
  2289.                     PrClose;
  2290.                 end;
  2291.             SetPort(savePort);
  2292.         end;
  2293.     
  2294.     
  2295.     Procedure DoMyUpdate;
  2296.         var
  2297.             savePort        :grafPtr;
  2298.             tempWindow    :windowPtr;
  2299.         begin
  2300.             tempWindow:=WindowPtr(myEvent.message);
  2301.             GetPort(savePort);
  2302.             SetPort(tempWindow);
  2303.             BeginUpdate(tempWindow);
  2304.             if tempWindow=DrawWindow then
  2305.                 begin
  2306.                     DrawContents;
  2307.                     DrawPalette;
  2308.                 end;
  2309.             EndUpdate(tempWindow);
  2310.             SetPort(savePort);
  2311.         end;
  2312.     
  2313.     
  2314.     Procedure DoJamAbout;
  2315.         const
  2316.             picID    =    999;
  2317.         var
  2318.             AboutWindow    :    WindowPtr;
  2319.             AboutPict    :    PicHandle;
  2320.             AboutRect    :    Rect;
  2321.             AboutEvent    :    Eventrecord;
  2322.             SavePort        :    GrafPtr;
  2323.             x1,y1,x2,y2    :    Integer;
  2324.         begin
  2325.             GetPort(SavePort);
  2326.             AboutPict:=PicHandle(GetResource('PICT',999));
  2327.             RsrcErr;
  2328.             
  2329.             with ScreenBits.Bounds do
  2330.                 begin
  2331.                     x1:=right-left;
  2332.                     y1:=bottom-top;
  2333.                 end;
  2334.             with AboutPict^^.picFrame do
  2335.                 begin
  2336.                     x2:=right-left;
  2337.                     y2:=bottom-top;
  2338.                 end;
  2339.             
  2340.             SetRect(AboutRect,1,1,x2,y2);
  2341.             AboutWindow:=NewWindow(Nil,AboutRect,'',false,1,Pointer(-1),false,0);
  2342.             MoveWindow(AboutWindow,(x1-x2) Div 2,(y1-y2) Div 2,true);
  2343.             ShowWindow(AboutWindow);
  2344.             SetPort(AboutWindow);
  2345.             with AboutPict^^.picFrame do
  2346.                 SetRect(AboutRect,0,0,right-left,bottom-top);
  2347.             DrawPicture(AboutPict,AboutRect);
  2348.             
  2349.             Repeat
  2350.                 CheckQueue;
  2351.             Until MyGetNextEvent(mdownMask+keyDownMask+AutoKeyMask,AboutEvent);
  2352.             
  2353.             ReleaseResource(handle(AboutPict));
  2354.             RsrcErr;
  2355.             
  2356.             DisposeWindow(AboutWindow);
  2357.             SetPort(SavePort);
  2358.         end;
  2359.     
  2360.     
  2361.     Procedure DoCommand(mResult:longint);        { handle menu commands }
  2362.         var
  2363.             name    :    Str255;
  2364.         begin
  2365.             theMenu := HiWord(mResult);
  2366.             theItem := LoWord(mResult);
  2367.             if BitAnd(myEvent.modifiers,CmdKey) <> 0 then
  2368.                 HiliteMenu(theMenu);
  2369.             case theMenu of
  2370.                 255:  If theItem <> 1 then
  2371.                             begin
  2372.                                 GetItem(myMenus[appleMenu],theItem,name);
  2373.                                 refnum:=OpenDeskAcc(name);
  2374.                             end
  2375.                         else If WindowPeek(FrontWindow)^.windowKind > 0 then
  2376.                                 DoJamAbout
  2377.                             else
  2378.                                 SysBeep(1);
  2379.                 256:    case theItem of                    { main menu }
  2380.                             1: LoadPic;
  2381.                             2: SavePic(false);
  2382.                             3: SavePic(true);
  2383.                             { ------- }
  2384.                             5: DoPageSetUp;
  2385.                             6: PrintPic;
  2386.                             { ------- }
  2387.                             8: If Continue then
  2388.                                     doneFlag:=true;
  2389.                             10:begin
  2390.                                     PrDebug := not PrDebug;
  2391.                                     if PrDebug then
  2392.                                         begin
  2393.                                             PrCtlCall(iPrDevCtl,$00010000,0,0);
  2394.                                             debug('---> Debug transcript follows');
  2395.                                         end;
  2396.                                 end;
  2397.                         end;
  2398.                 257:    ChangeFont;
  2399.                 258:    ChangeSize;
  2400.                 259:    ChangeStyle;
  2401.                 260:    case theItem of
  2402.                             1: FadeIn(drawWindow^.portRect,UT[0].thePat);
  2403.                             2: FadeOut(drawWindow^.portRect,UT[0].thePat);
  2404.                             3: FadeInto(drawWindow^.portRect,black,white);
  2405.                         end;
  2406.             end;
  2407.             HiliteMenu(0);
  2408.         end;
  2409.     
  2410.     
  2411.     Procedure InitTables;        { initialize User Table, Queue }
  2412.         var
  2413.             i        :integer;
  2414.             
  2415.         begin
  2416.             with PQ do            { empty queue }
  2417.                 begin
  2418.                     head := 0;
  2419.                     tail := 0;
  2420.                 end;
  2421.             with UT[0] do
  2422.                 begin
  2423.                     id := myNode;
  2424.                     theTool := dTool;                    { default tool }
  2425.                     theMode := dMode;                    { default mode }
  2426.                     thePat := black;                    { default pattern }
  2427.                     theClr := theColors[dColor];    { default to black }
  2428.                     hSize := dPen;                        { default pensize }
  2429.                     vSize := dPen;                        { default pensize }
  2430.                     theFnum := applFont;                { default text font }
  2431.                     theFsize := dSize;                { default text size }
  2432.                     theFstyle := dStyle;                { default text style }
  2433.                     x := 100;                            { somewhere on the screen }
  2434.                     y := 50;
  2435.                     splatSpeed := dsplatterCount;    { default speed }
  2436.                     splatRad := dsplatRad;            { default radius }
  2437.                     
  2438.                     { time needs no initialization }
  2439.                 end;
  2440.             for i := 1 to maxUsers do
  2441.                 begin
  2442.                     UT[i] := UT[0];
  2443.                     UT[i].id := -1;                { invalidate all users }
  2444.                 end;
  2445.         end;
  2446.     
  2447.     
  2448.     Procedure ReadPatCol;    { read patterns and colors into memory }
  2449.         var
  2450.             RGBColors        :CHandle;
  2451.             i                    :integer;
  2452.             
  2453.         begin
  2454.             for i:=1 to 8 do
  2455.                 GetIndPattern(thePatterns[i],128,i);
  2456.                 
  2457.             RGBColors:=CHandle(GetResource('CLRS',128));
  2458.             RsrcErr;
  2459.             
  2460.             theColors:=RGBColors^^;
  2461.             
  2462.             ReleaseResource(handle(RGBColors));
  2463.             RsrcErr;
  2464.         end;
  2465.     
  2466.     
  2467.     Procedure InitGlob;        { init globals, user table, etc. }
  2468.         const
  2469.             UnImplTrapNum                    =    $9F;        { * Unimplemented trap * }
  2470.             WaitNextEventTrapWord        =    $60;
  2471.         var
  2472.             i,j                :integer;
  2473.             Rom,Machine        :integer;
  2474.             theWorld            :SysEnvRec;
  2475.         begin
  2476.             { * Get the world, so to speak * }
  2477.             if SysEnvirons(1,theWorld)<>envNotPresent then
  2478.                 begin
  2479.                     MultiFinderRunning:=(theWorld.machineType>=0) & (NGetTrapAddress(WaitNextEventTrapWord,ToolTrap)<>NGetTrapAddress(UnImplTrapNum,ToolTrap));
  2480.                     ColorQDrawImplm:=theWorld.hasColorQD;
  2481.                 end
  2482.             else
  2483.                 begin
  2484.                     MultiFinderRunning:=false;
  2485.                     ColorQDrawImplm:=false;
  2486.                 end;
  2487.             
  2488.             Environs(Rom,Machine);
  2489.             if Machine=2
  2490.                 then
  2491.                     MacII:=true
  2492.                 else
  2493.                     MacII:=false;
  2494.             PixDraw:=false;    { * Controls if mac II pix map shit is working or not * }
  2495.             MacII:=false;
  2496.             
  2497.             PrDrvrOpen;
  2498.             PrDebug := false;                { *** for debugging only *** }
  2499.             
  2500.             err := MPPOpen;    { open Appletalk driver }
  2501.             if err<>noErr then
  2502.                 begin
  2503.                     SysBeep(1);
  2504.                     exitToShell;
  2505.                 end;
  2506.             
  2507.             err := GetNodeAddress(myNode,myNet);    { who am I? I don't know }
  2508.             if err<>noErr then
  2509.                 begin
  2510.                     SysBeep(1);
  2511.                     exitToShell;
  2512.                 end;
  2513.             
  2514.             err := LapOpenProtocol(OurType,nil);    { open our protocol type }
  2515.             if err<>noErr then
  2516.                 begin
  2517.                     SysBeep(1);
  2518.                     exitToShell;
  2519.                 end;
  2520.             
  2521.             LAPrh := ABRecHandle(newHandle(lapSize));    { handle for LAP reads }
  2522.             LAPwh := ABRecHandle(newHandle(lapSize));    { handle for LAP writes }
  2523.             HLock(handle(LAPrh));
  2524.             HLock(handle(LAPwh));
  2525.  
  2526.             hPrint:=THPrint(NewHandle(SizeOf(TPrint)));
  2527.             
  2528.             SetUpRead;            { set up initial LAPRead }
  2529.             palette := PicHandle(GetResource('PICT',1000));
  2530.             RsrcErr;
  2531.             jamPic := PicHandle(GetResource('PICT',1001));
  2532.             RsrcErr;
  2533.             
  2534.             for i := 1 to 20 do
  2535.                 begin
  2536.                     j := (i-1) div 2;
  2537.                     if odd(i) then
  2538.                         SetRect(ToolRects[i],0,20*j,22,20*(j+1)-1)
  2539.                     else
  2540.                         SetRect(ToolRects[i],23,20*j,45,20*(j+1)-1);
  2541.                 end;
  2542.             SetRect(curPatRect,3,203,42,225);
  2543.             SetRect(hSizeRect,0,231,21,266);
  2544.             SetRect(vSizeRect,23,231,44,266);
  2545.             
  2546.             PatternsUp := true;
  2547.             curPat := 1;
  2548.             curColor := 1;
  2549.             ReadPatCol;
  2550.             PatternsUp:=true;
  2551.             for i := 0 to 15 do
  2552.                 theCurs.mask[i] := 0;
  2553.             setPt(theCurs.hotspot,0,0);
  2554.             setPt(theECurs.hotspot,0,0);
  2555.             arrowCurs := true;
  2556.             updateCurs := false;
  2557.             
  2558.             InitTables;
  2559.             
  2560.             OpenDrawWindow;
  2561.             
  2562.             textMode(SrcCopy);
  2563.             
  2564.             clickTime := 0;        { set up doubleclick variables }
  2565.             lastTool := -1;
  2566.             DoneFlag := false;
  2567.             theSizeidx := 3;
  2568.             changed := false;
  2569.             
  2570.             theSizer:=GetCursor(1000);
  2571.             theHand:=GetCursor(1001);
  2572.             thePlacer:=GetCursor(1002);
  2573.             theSprayer:=GetCursor(1003);
  2574.         end;
  2575.     
  2576.     
  2577.     Procedure CleanUp;
  2578.         {
  2579.             All of this isn't really necessary except for closing our
  2580.             protocol type. The application heap will be flushed anyway,
  2581.             but we ought to set a good example....
  2582.         }
  2583.         begin
  2584.             PrDrvrClose;
  2585.             
  2586.             if LAPrh^^.abResult=1 then            { stop LAP read if still in progress }
  2587.                 begin
  2588.                     err := LAPRdCancel(LAPrh);
  2589.                     DoErr(1004);
  2590.                 end;
  2591.             
  2592.             if not polling then
  2593.                 begin
  2594.                     err := VRemove(@myTask);                { remove VBLTask }
  2595.                     DoErr(1005);
  2596.                 end;
  2597.             
  2598.             err := LAPCloseProtocol(OurType);    { !! close protocol !! }
  2599.             DoErr(1000);
  2600.             
  2601.             err := MPPClose;                            { close AppleTalk driver }
  2602.             DoErr(1002);
  2603.             
  2604.             DisposHandle(handle(LAPrh));
  2605.             DisposHandle(handle(LAPwh));
  2606.             releaseResource(handle(palette));
  2607.             RsrcErr;
  2608.             releaseResource(handle(jamPic));
  2609.             RsrcErr;
  2610.             if PixDraw
  2611.                 then
  2612.                     begin
  2613.                         
  2614.                     end
  2615.                 else
  2616.                     DisposPtr(bmap.baseAddr);
  2617.         end;
  2618.     
  2619.     procedure _DataInit;EXTERNAL;
  2620.  
  2621.     begin
  2622.         UnloadSeg(@_DataInit);        { * Get rid of MPW's init code * }
  2623.         
  2624.         FlushEvents(everyEvent,0);
  2625.         InitGraf(@thePort);
  2626.         InitFonts;
  2627.         TEInit;
  2628.         InitWindows;
  2629.         InitDialogs(Nil);
  2630.         InitCursor;
  2631.         SetUpMenus;
  2632.         InitGlob;
  2633.         Repeat
  2634.             FixCursor;
  2635.             CheckQueue;        { something for us to do while we idle }
  2636.             if MyGetNextEvent(everyEvent,myEvent) then
  2637.                 with myEvent do
  2638.                     case what of
  2639.                         mouseDown:
  2640.                             begin
  2641.                                 mods := modifiers;
  2642.                                 code := FindWindow(where,tempWindow);
  2643.                                 case code of
  2644.                                     inMenuBar:        DoCommand(MenuSelect(where));
  2645.                                     InSysWindow:    SystemClick(myEvent,tempWindow);
  2646.                                     inContent,InDrag:
  2647.                                                     if tempWindow <> frontWindow then
  2648.                                                         begin
  2649.                                                             SelectWindow(tempWindow);
  2650.                                                             SetPort(tempWindow);
  2651.                                                         end
  2652.                                                     else if FrontWindow=DrawWindow then
  2653.                                                         begin
  2654.                                                             GlobalToLocal(where);
  2655.                                                             MasterClick(where);
  2656.                                                         end;
  2657.                                 end;
  2658.                             end;
  2659.                         keyDown, autoKey:
  2660.                             begin
  2661.                                 theChar := chr(BitAnd(message,255));
  2662.                                 if BitAnd(modifiers,CmdKey)<>0 then
  2663.                                     begin
  2664.                                         if theChar in ['v','V'] then
  2665.                                             PastePicture
  2666.                                         else
  2667.                                             DoCommand(MenuKey(theChar))
  2668.                                     end
  2669.                                 else
  2670.                                     MasterKey(theChar);
  2671.                             end;
  2672.                         updateEvt:
  2673.                                 DoMyUpdate;
  2674.                         activateEvt:
  2675.                                 if Odd(modifiers) then
  2676.                                     begin
  2677.                                         tempWindow:=WindowPtr(message);
  2678.                                         SetPort(tempWindow);
  2679.                                         If tempWindow=DrawWindow then
  2680.                                             begin
  2681.                                                 updateCurs:=true;
  2682.                                                 { * Remove Edit menu/ we don't use it, but DAs might * }
  2683.                                                 If FileMenuPresent then
  2684.                                                     begin
  2685.                                                         FileMenuPresent:=false;
  2686.                                                         DeleteMenu(261);
  2687.                                                         DrawMenuBar;
  2688.                                                     end;
  2689.                                             end
  2690.                                         else
  2691.                                             SetCursor(arrow);
  2692.                                     end
  2693.                                 else
  2694.                                     begin
  2695.                                         { * If our about window caused it then give them an Edit menu * }
  2696.                                         if (WindowPtr(message)=DrawWindow) & (not FileMenuPresent) & (windowPeek(FrontWindow)^.windowKind<0) then
  2697.                                             begin
  2698.                                                 FileMenuPresent:=true;
  2699.                                                 InsertMenu(myMenus[EditMenu],257);
  2700.                                                 DrawMenuBar;
  2701.                                             end;
  2702.                                     end;
  2703.                     end;
  2704.         Until doneflag;
  2705.         CleanUp;
  2706.         SetCursor(GetCursor(WatchCursor)^^);
  2707.     end.
  2708.